package ssm.ann.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.ExecutorType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;

import javax.sql.DataSource;
import java.io.IOException;

// MyBatis DAO 层接口扫描
@MapperScan("ssm.ann.mapper")
// 加载 properties 文件
@PropertySource("classpath:db.properties")
// 扫描包路径，spring 扫描除 controller 层以外的，spring 不可从子容器(spring mvc)中获取 bean
@ComponentScan(basePackages = {"ssm.ann"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, ControllerAdvice.class})
})
public class RootConfig {

    /**
     * SqlSession 工厂
     *
     * @param dataSource 数据源，会在 IOC 中获取
     */
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // 设置 MyBatis 配置文件路径
        factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        // 设置 SQL 映射文件路径
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        // 设置 JavaBean 类型别名，在 SQL 映射文件中就不用写全类名
        factoryBean.setTypeAliasesPackage("ssm.pojo");
        return factoryBean;
    }

    /**
     * Druid 数据源
     */
    @Bean
    public DataSource getDataSource(@Value("${db.username}") String name, @Value("${db.password}") String password, @Value("${db.url}") String url) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(name);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * 扫描所有 mapper 接口的实现，让这些 mapper 能够自动注入
     */
    // @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("ssm.ann.mapper");
        return mapperScannerConfigurer;
    }

    /**
     * 配置一个可以进行批量执行的 sqlSession
     */
    @Bean
    public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception {
        /**
         * Simple Executor -- SIMPLE 普通的执行器，默认
         * Reuse Executor -执行器会重用预处理语句（prepared statements）
         * Batch Executor --批量执行器
         */
        SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject(), ExecutorType.BATCH);
        return sessionTemplate;
    }
}